﻿namespace System.ServiceModel.DomainServices.Client
{
    using System;
    using System.Runtime.InteropServices;

    public sealed class DomainOperationException : Exception
    {
        private DomainOperationExceptionData _data;

        public DomainOperationException() : this(null, null, OperationErrorStatus.ServerError, 0, null)
        {
        }

        public DomainOperationException(string message) : this(message, null, OperationErrorStatus.ServerError, 0, null)
        {
        }

        public DomainOperationException(string message, Exception innerException) : this(message, innerException, OperationErrorStatus.ServerError, 0, null)
        {
        }

        internal DomainOperationException(string message, DomainOperationException exception) : this(message, exception.InnerException, exception.Status, exception.ErrorCode, exception.StackTrace)
        {
        }

        public DomainOperationException(string message, OperationErrorStatus status) : this(message, null, status, 0, null)
        {
        }

        public DomainOperationException(string message, OperationErrorStatus status, int errorCode) : this(message, null, status, errorCode, null)
        {
        }

        public DomainOperationException(string message, OperationErrorStatus status, int errorCode, string stackTrace) : this(message, null, status, errorCode, stackTrace)
        {
        }

        private DomainOperationException(string message, Exception innerException, OperationErrorStatus status, int errorCode, string stackTrace) : base(message, innerException)
        {
            this._data = new DomainOperationExceptionData();
            this._data.Status = status;
            this._data.StackTrace = stackTrace;
            this._data.ErrorCode = errorCode;
        }

        public int ErrorCode
        {
            get
            {
                return this._data.ErrorCode;
            }
            set
            {
                this._data.ErrorCode = value;
            }
        }

        public override string StackTrace
        {
            get
            {
                if (this._data.StackTrace != null)
                {
                    return this._data.StackTrace;
                }
                return base.StackTrace;
            }
        }

        public OperationErrorStatus Status
        {
            get
            {
                return this._data.Status;
            }
            set
            {
                this._data.Status = value;
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct DomainOperationExceptionData
        {
            public OperationErrorStatus Status;
            public string StackTrace;
            public int ErrorCode;
        }
    }
}

